home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS16.ADF / C / InputHandler / in.c < prev    next >
C/C++ Source or Header  |  1989-01-27  |  12KB  |  431 lines

  1. /* 
  2.  
  3. Input handler for use with TxEd. 
  4.  
  5. This module will only work with MANX C because it does two things.
  6.  
  7. 1. It has inline assembly code that uses manx directives
  8. 2. It assumes the manx SMALL data/code memory model.
  9.  
  10. Point 2 is crucial. In order to use the Manx library, register A4 must be
  11. set prior to calling any runtime library routines such as permit() and forbid().
  12. So, the first thing done in the main routine is to call a small assembler
  13. fragment (_GetA4) that returns the current value of A4. This is stored in a
  14. global variable (_mya4) so that when the input handler gets called (its called
  15. as an interrupt handler in the context of the input device and not the context
  16. of the rest of the program) register A4 must be set prior to calling any C
  17. code. See _HandlerInterface at the bottom of this module.
  18.  
  19. Note that although the small code/data model is assumed (so that A4 will be
  20. set up properly at the beginning of function main) the assembly code must
  21. use large code/data and is thus placed at the end of the file. It must use
  22. the large model so that the instruction that loads A4 from _mya4 uses absolute
  23. addressing instead of an offset to A4 (which isn't set up yet - thats what
  24. the code does!!).
  25.  
  26. */
  27.  
  28.  
  29.  
  30. #include <exec/types.h>
  31. #include <exec/ports.h>
  32. #define function     /*  this is just used by the indenter  */
  33. #define then     {
  34. #define elsif    } else if
  35. #define els      } else  {
  36. #define fi       }
  37. #define forever  for (;;) {
  38. #define rof      }
  39. #define or ||
  40. #define and &&
  41. #define not !
  42. #define NIL 0L
  43.  
  44. #define z if(1==0)
  45. #include <devices/timer.h>
  46. #include <exec/memory.h>
  47. /* #include <exec/io.h>    */
  48. /* #include <exec/tasks.h> */
  49. #include <exec/interrupts.h>
  50. #include <devices/input.h>
  51. #include <exec/devices.h>
  52. #include <devices/inputevent.h>
  53.  
  54. #define gev(the__ev,v_code,v_qual,v_link) the__ev.ie_NextEvent = v_link; \
  55.         the__ev.ie_Class        = IECLASS_RAWKEY; \
  56.     /*     the__ev.ie_SubClass        = 0; */        \
  57.          the__ev.ie_Code            = v_code;    \
  58.          the__ev.ie_Qualifier        = v_qual;      \
  59.     /*     the__ev.ie_X            = 0; */     \
  60.     /*     the__ev.ie_Y            = 0; */     \
  61.     /*     the__ev.ie_TimeStamp.tv_secs    = 0; */     \
  62.     /*     the__ev.ie_TimeStamp.tv_micro    = 0; */
  63.  
  64.  
  65. #define ctime(the__ev,e_v) \
  66.     the__ev.ie_TimeStamp.tv_secs=e_v->ie_TimeStamp.tv_secs;\
  67.     the__ev.ie_TimeStamp.tv_micro=e_v->ie_TimeStamp.tv_micro;
  68.  
  69.  
  70. struct InputEvent  copyevent;
  71.  
  72. struct InputEvent  ev_b1= 0;  /* to create a right-amiga-B sequence */
  73. struct InputEvent  ev_b2= 0;
  74.  
  75. struct InputEvent  ev_c1= 0;  /* to create a right-amiga-C sequence */
  76. struct InputEvent  ev_c2= 0;
  77.  
  78. struct InputEvent  ev_x1= 0;  /* to create a right-amiga-X sequence */
  79. struct InputEvent  ev_x2= 0;
  80.  
  81. struct InputEvent  ev_i1= 0;  /* to create a right-amiga-I sequence */
  82. struct InputEvent  ev_i2= 0;
  83.  
  84. struct InputEvent  ev_d1= 0;  /* to create a right-amiga-d sequence */
  85. struct InputEvent  ev_d2= 0;
  86.  
  87. struct InputEvent  ev_u1= 0;  /* to create a right-amiga-u sequence */
  88. struct InputEvent  ev_u2= 0;
  89.  
  90. struct InputEvent  ev_t1= 0;  /* to create a right-amiga-t sequence */
  91. struct InputEvent  ev_t2= 0;
  92.  
  93. struct InputEvent  ev_f1= 0;  /* to create a right-amiga-f sequence */
  94. struct InputEvent  ev_f2= 0;
  95.  
  96.  
  97.  
  98. struct MsgPort    *inputDevPort;
  99. struct IOStdReq   *inputRequestBlock;
  100. struct Interrupt   handlerStuff;
  101. struct InputEvent  dummyEvent;
  102. struct MsgPort    *CreatePort();
  103. struct IOStdReq   *CreateStdIO();
  104. struct MemEntry    me[10];
  105. struct timerequest *PrepareTimer();
  106.  
  107. extern long OpenDevice();
  108. extern Enable_Abort;
  109. extern long SysBase;
  110.  
  111. int hcount = 0;
  112. long int p1,p2,p3;
  113. static     char     str_buf[BUFSIZ];  /* used for buffered i/o  to terminal */
  114.  
  115. int enable_cut_paste = 1;
  116. int exit_now = 0;
  117.  
  118. function struct InputEvent *myhandler(ev,mydata) register struct InputEvent *ev; struct MemEntry *mydata[]; {
  119.     struct InputEvent *ret;
  120.     register int evQ,evC;
  121.  
  122.     ret = ev;
  123.     p3 = SysBase;
  124.     hcount++; p1 = (long)ev; p2 = (long)mydata;
  125.     
  126.     if(ev->ie_Class == IECLASS_TIMER) then
  127.         return ret;
  128.     els    
  129.       evQ = ev->ie_Qualifier;
  130.       evC = ev->ie_Code;
  131.            if(     ev->ie_Class == IECLASS_RAWKEY ) then
  132.             if( (evC == 0x60 or evC == 0x61) and evQ == 0x8003) then
  133.             enable_cut_paste = 1 - enable_cut_paste ;
  134.             elsif (evC == 0xe1 and evQ == 0x8009) then
  135.             enable_cut_paste = 0;
  136.             exit_now     = 1;/* right shift up with ctrl and left shift down */
  137.             fi
  138.            fi
  139.  
  140.         Forbid();        /* keyboard and our interceptions */ 
  141.         if (enable_cut_paste and ev->ie_Class == IECLASS_RAWKEY ) then
  142.            if ((evQ == 0x8010 or evQ == 0xc010) and evC == 0x64) then  /* left alt down */
  143.               ret = &ev_b1;
  144.            elsif ((evQ == 0x8000 or evQ == 0xc000) and evC == 0xe4) then /* l alt up */
  145.               ret =  &ev_c1;             
  146.            elsif (evQ == 0x8040 and evC == 0x66) then /* l amiga down */
  147.               ret =  NULL;             
  148.            elsif (evQ == 0x8000 and evC == 0xe6) then /* l amiga up */
  149.               ret =  &ev_i1;             
  150.            elsif (evQ == 0x8011 and evC == 0x64) then /* shift l alt down */
  151.               ret = &ev_b1;
  152.            elsif (evQ == 0x8001 and evC == 0xe4) then /* shift l alt up */
  153.               ret =  &ev_x1;
  154.            elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x50) then /* f1 down */
  155.               ret =  &ev_d1;
  156.            elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x51) then /* f2 down */
  157.               ret =  &ev_u1;
  158.            elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x55) then /* f2 down */
  159.               ret =  &ev_f1;
  160.            elsif (  evQ == 0x8000 and evC == 0x52) then /* f3 down */
  161.               ret =  &ev_t1;
  162.            fi   
  163.         fi
  164.         Permit();
  165.     fi
  166.     return ret;
  167.     
  168. }    
  169.  
  170. extern struct Task *FindTask();
  171. struct Task *mytask;
  172. LONG mysingnal;
  173. extern VOID HandlerInterface();
  174.  
  175. struct timerequest *mytimerRequest;
  176. extern struct timerequest *PrepareTimer();
  177. extern long int WaitTimer();
  178. extern void     DeleteTimer();
  179. extern VOID ewindow();
  180. struct IntuitionBase      *IntuitionBase;
  181.     extern struct IntuitionBase *OpenLibrary();
  182.  
  183. LONG my_a4 = 0; extern LONG GetA4();
  184. function void main(argc,argv) int argc; char **argv; {
  185.  
  186.     long error;
  187.     ULONG oldseconds,oldmicro,oldclass;
  188.  
  189.     IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
  190.     if ( IntuitionBase == NULL) then
  191.         return;
  192.     fi
  193.     my_a4 = GetA4();  /* need current base for interrupt handler */
  194.  
  195.     gev(ev_b1,0x35,0x8080,&ev_b2);  /* set up an amiga-b */ /* b down */
  196.     gev(ev_b2,0xb5,0x8080,NULL  );                /* b up   */
  197.  
  198.     gev(ev_i1,0x17,0x8080,&ev_i2);  /* set up an amiga-i */
  199.     gev(ev_i2,0x97,0x8080,NULL );
  200.     
  201.     gev(ev_x1,0x32,0x8080,&ev_x2);  /* set up an amiga-x */
  202.     gev(ev_x2,0xb2,0x8080,NULL );
  203.  
  204.     gev(ev_c1,0x33,0x8080,&ev_c2);  /* set up an amiga-c */
  205.     gev(ev_c2,0xb3,0x8080,NULL );
  206.  
  207.     gev(ev_d1,0x22,0x8080,&ev_d2);  /* set up an amiga-d */
  208.     gev(ev_d2,0xa2,0x8080,NULL  );
  209.  
  210.     
  211.     gev(ev_u1,0x16,0x8080,&ev_u2);  /* set up an amiga-u */
  212.     gev(ev_u2,0x96,0x8080,NULL );
  213.     
  214.     gev(ev_t1,0x14,0x8080,&ev_t2);  /* set up an amiga-t */
  215.     gev(ev_t2,0x94,0x8080,NULL );
  216.     
  217.     gev(ev_f1,0x23,0x8080,&ev_f2);  /* set up an amiga-f */
  218.     gev(ev_f2,0xa3,0x8080,NULL );
  219.     
  220.  
  221.     
  222.  
  223.     dummyEvent.ie_Class = IECLASS_NULL;
  224.     dummyEvent.ie_NextEvent = NULL;
  225.  
  226.     inputDevPort = CreatePort(0L,0L);
  227.     if(inputDevPort == NULL) then
  228.         ewindow("Can't open input device",NIL);
  229.         exit(-1);
  230.     fi
  231.  
  232.     inputRequestBlock = CreateStdIO(inputDevPort);
  233.     if (inputRequestBlock == NULL) then 
  234.         DeletePort(inputDevPort);
  235.         ewindow("Can't CreateStdIO",NIL);
  236.         exit(-2);
  237.     fi
  238.     mytimerRequest = PrepareTimer(1);
  239.     if (mytimerRequest == NULL) then
  240.         ewindow("Can't init timer",NIL);
  241.         exit(-3);
  242.     fi
  243.  
  244.     handlerStuff.is_Data       = (APTR) &me[0];
  245.     handlerStuff.is_Code       = HandlerInterface;
  246.     handlerStuff.is_Node.ln_Pri= 127;
  247.  
  248.     error = OpenDevice("input.device",0L,inputRequestBlock,0L);
  249.     if (error != NULL ) then
  250.         ewindow("Can't open input.device",NIL);
  251.         exit(-4);
  252.     fi
  253.     inputRequestBlock->io_Command = IND_ADDHANDLER;
  254.     inputRequestBlock->io_Data    = (APTR) &handlerStuff;
  255.  
  256.     DoIO(inputRequestBlock); 
  257.     copyevent.ie_TimeStamp.tv_secs  = 0;
  258.     copyevent.ie_TimeStamp.tv_micro = 0;
  259.     copyevent.ie_Class         = 0;
  260.  
  261.  
  262.     oldseconds = 0;
  263.     oldmicro   = 0;
  264.     oldclass   = 0;
  265.  
  266.     Enable_Abort = 0;
  267.     forever
  268.         WaitForTimer(mytimerRequest,0L,100000L); /* 1/10'th second */
  269.         if (exit_now) then /* check for exit */
  270.             break;
  271.         fi
  272.      rof
  273.     inputRequestBlock->io_Command = IND_REMHANDLER;
  274.     inputRequestBlock->io_Data    = (APTR) &handlerStuff;
  275.     DoIO(inputRequestBlock); 
  276.  
  277.       if (IntuitionBase) CloseLibrary(IntuitionBase);
  278.  
  279.     CloseDevice(inputRequestBlock);
  280.     DeleteStdIO(inputRequestBlock);
  281.     DeletePort(inputDevPort);
  282.     DeleteTimer(mytimerRequest);
  283. }
  284.  
  285. function showEvents(e) struct InputEvent *e; {
  286.  
  287. }
  288.  
  289.  
  290. extern struct MsgPort *CreatePort();
  291. extern struct IORequest *CreateExtIO();
  292.  
  293.  
  294. function struct timerequest *PrepareTimer(precision) register SHORT precision; {
  295.  
  296.     register long int error; register long whichunit;
  297.  
  298.     register struct MsgPort *timerport;
  299.     register struct timerequest *timermsg;
  300.  
  301.     timerport = CreatePort(0L,0L);
  302.  
  303.     if (timerport == NULL) then
  304.         /* printf("no port\n"); */
  305.         return NULL;
  306.     fi
  307.  
  308.  
  309.     timermsg =(struct timerequest *) CreateExtIO(timerport,(long)sizeof(struct timerequest));
  310.     if (timermsg == NULL) then
  311.         /* printf("no timermsg\n"); */
  312.         DeletePort(timerport);
  313.         return NULL;
  314.  
  315.     fi
  316.  
  317.     if (precision) then
  318.         whichunit = UNIT_MICROHZ;
  319.     els
  320.         whichunit = UNIT_VBLANK;
  321.     fi
  322.  
  323.     error = OpenDevice(TIMERNAME,whichunit,timermsg,0L);
  324.     if (error != NULL) then
  325.         /* printf("opendevice = %ld\n",error); */
  326.         DeleteExtIO(timermsg,sizeof(struct timerequest));
  327.         DeletePort(timerport);
  328.         return NULL;
  329.     fi
  330.     return timermsg;
  331.  
  332. }
  333.  
  334. function WaitForTimer(tr,seconds,microseconds) 
  335.             ULONG seconds,microseconds; register struct timerequest *tr; {
  336.  
  337.     tr->tr_node.io_Command = TR_ADDREQUEST;
  338.     tr->tr_time.tv_secs    = seconds;
  339.     tr->tr_time.tv_micro   = microseconds;
  340.     DoIO(tr);
  341.  
  342.     return 0;
  343.  
  344.  
  345. }
  346. function VOID ewindow(str, parm) char *str; char *parm;
  347. {
  348.          ewindow_int(str,parm,0);
  349. }
  350. function bwindow(str, parm) char *str; char *parm;
  351. {
  352.          return ewindow_int(str,parm,1);
  353. }
  354. function long between(a,b,c)
  355.         register long a,b,c;
  356. {
  357.         if (b <= a) then
  358.            return a;
  359.         elsif (b >= c) then
  360.            return c;
  361.         fi
  362.         return b;
  363. }
  364.  
  365. function static short int ewindow_int(str, parm,bool) char *str; char *parm; short int bool;
  366.  
  367. {
  368.    static struct IntuiText t3 = { 2,1,0,5,3,NULL,(UBYTE *)"CANCEL",NULL };
  369.    static struct IntuiText t2 = { 2,1,0,5,3,NULL,(UBYTE *)"Ok",NULL };
  370.    static struct IntuiText t1 = { 2,1,0,15,7,NULL,NULL,NULL };
  371.    char mess[86];
  372.    register struct IntuiText *pt;
  373.    extern long AutoRequest(),IntuiTextLength();
  374.  
  375.    if (bool) then
  376.       pt = &t3;
  377.    els
  378.       pt = &t2;
  379.    fi
  380.    
  381.    mess[0] = '\0';
  382.    strncat(mess,str,80);
  383.    strncat(mess," ",80);
  384.    strncat(mess,parm,80);
  385.    mess[79] = '\0';
  386.    t1.IText = (UBYTE *) mess;
  387.    return (short int) AutoRequest(NIL,&t1,&t2,pt,NIL,NIL,
  388.     between(150L,(long) IntuiTextLength(&t1)+65L,639L),50L);
  389. }
  390.  
  391.  
  392. function void DeleteTimer(tr) register struct timerequest *tr; {
  393.     register struct MsgPort *tp;
  394.     
  395.     tp = tr->tr_node.io_Message.mn_ReplyPort;
  396.     if (tr != 0) then
  397.         CloseDevice(tr);
  398.         DeleteExtIO(tr,sizeof(struct timerequest));
  399.     fi    
  400.     if (tp != 0) then
  401.         DeletePort(tp);
  402.     fi
  403.     return ;
  404. #ifndef _lint    
  405. #asm
  406.  
  407.  
  408. ;-------------------------------------------------------------------------
  409. ; MAKE SURE THIS ASSEMBLY CODE IS AT THE END OF THIS C SOURCE FILE
  410. ;-------------------------------------------------------------------------
  411.     far code    ;make sure the below can load a4 without using a4
  412.     far data    ;ditto
  413. _HandlerInterface:
  414.     movem.l        saver,-(sp)
  415.     move.l        _my_a4,a4
  416.     movem.l        a0/a1,-(a7)
  417.     
  418.     jsr        _myhandler
  419.     addq.l        #8,a7
  420.     movem.l        (sp)+,saver
  421.     rts
  422. saver:    reg    a0-a6/d1-d7
  423.  
  424. _GetA4:
  425.     move.l        a4,d0
  426.     rts
  427.  
  428. #endasm
  429. #endif
  430. }
  431.